/*************************************************************************
 *                                                                       *
 * This file is part of the DogosFrame distribution.  For full copyright *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_info_InfoManager_h
#define FreeMAPs_include_COMMON_info_InfoManager_h

#include "FreeMAPsConfig.h"

//C++ headers
#include <map>

//COMMON headers
#include "COMMON/base/Common.h"
#include "COMMON/tbox/Bimap.h"
#include "COMMON/tbox/StartupShutdownManager.h"



namespace FreeMAPs
{

//forward declarations
class InputDatabase;
class StateIndicator;
class CommonInfo;
class WriterInfo;
class MeshInfo;
class TimePatch;
class AttributeInfo;
class RegionInfo;
/**
 * this class is a container to have all info class
 * so that one can trans info from one function to another more conviently
 */
class InfoManager
{
public:

    /**
     * @return reference to common_info
     * common_info contains common information such as dim, file dir etc.
     */
    inline const CommonInfo*
    get_common_info() const;

    /**
     * @return a writable version of CommonInfo.
     */
    inline CommonInfo*
    get_common_info();

    /**
     * @return reference to writer info
     * writer info contain information of writer information such as which writer(VTK, VISIT...)
     * and how to write (where and when)
     */
    inline const WriterInfo*
    get_writer_info() const;

    inline WriterInfo*
    get_writer_info();

    /**
     * @return the mesh info.
     * mesh info tells whether the structured or unstructured mesh will be used.
     * it does not manager the mesh itself.
     */
    inline const MeshInfo*
    get_mesh_info() const;

    inline MeshInfo*
    get_mesh_info();

    /**
     * @return the TimeInfoManager.
     * TimeInfoManager will manager all the time info used in different ensemble.
     */
    inline const TimePatch*
    get_time_patch() const;

    /**
     * @return a writable version of TimeInfoManager.
     */
    inline TimePatch*
    get_time_patch();

    inline const bool
    is_un_steady() const;

    inline void
    set_un_steady(const bool is_un_steady);

    /**
      * @return reference to AttributeInfo
      * attribute info contain information of the physical domain's information such material property.
      * it does not tell a region what attribute it is.
      * it just tells what an attribute itself will be.
      */
     inline AttributeInfo*
     get_attribute_info() const;

     inline const RegionInfo*
     get_region_info() const;

     inline RegionInfo*
     get_region_info();

     inline const void
     set_mesh_file_name(const std::string mesh_file_name);

     inline const bool
     is_mesh_file_name_exist() const;

     //when read need to these info exist or not
     inline bool
     is_mesh_info_exist() const;

     inline bool
     is_attribute_info_exist() const;

     inline bool
     is_region_info_exist() const;


public:
    inline void
    set_input_file_name (
        const std::string& file_name);

    inline void
    remove_state_indicator(
        const StateIndicator* state_indicator) const;

    /**
     * Return a pointer to the single instance of the info manager.
     * All access to the info manager object is through get_manager().
     *
     * Note that when the manager is accessed for the first time, the
     * Singleton instance is registered with the StartupShutdownManager
     * class which destroys such objects at program completion.  Thus,
     * users of this class do not explicitly allocate or deallocate the
     * Singleton instance.
     */
    static InfoManager*
    get_instance();

    void
    register_state_indicator(
        const StateIndicator* state_indicator) const;

    /**
     * after close, no state indicator will be registered any more.
     * after close, some work can be done that should waiting all indicator is prepared.
     * now the work is build analytic function into c code if necessary.
     */
    void
    close();

    /**
     * clear all information
     */
    void
    clear_all_items();


    /**
     * @brief build the information
     * @param top_input_db contain all information need to build the class
     */
    void
    get_from_input (
        const InputDatabase* db);

    /**
     * @brief display information
     */
    friend std::ostream&
    operator << (
        std::ostream& os,
        const InfoManager& rhs);

    /*
     * Deallocate the restart manager instance.  It is not necessary to call
     * this routine at program termination, since it is automatically called
     * by the StartupShutdownManager class.
     */
    static void
    shutdown_callback();

    bool
    check_all_info_db(const InputDatabase* db);


private:

    /*
     * constructor function. set to private to prevent been accessed.
     * one can access this class by get_instance().
     */
    InfoManager();

    /*
     * build all the point objects
     */
    void
    create_objects ();

private:

    /*
     * all information is read from an input file.
     * save the file name for log.
     */
    std::string d_input_file_name;

    CommonInfo* d_common_info;

    WriterInfo* d_writer_info;

    MeshInfo* d_mesh_info;

    // use TimePatch for TimeInfo
    TimePatch* d_time_patch;

    bool d_is_un_steady;//un_steady have time_info

    AttributeInfo* d_attribute_info;

    RegionInfo* d_region_info;

    std::string d_mesh_file_name;

    //when read, need know these info exist or not
    bool d_is_mesh_info_exist;
    bool d_is_attribute_info_exist;
    bool d_is_region_info_exist;


private:
    /*
     * map<state_indicator, full_name>
     * save all the state_indicator here, so that after all the objects have been build,
     * check if all them are consistence.
     * do not manager the memory of the state_indicators.
     */
    mutable Bimap<const StateIndicator*, std::string> d_all_state_indicators;

    /*
     * when is closed, do not register state indicator anymore.
     */
    bool d_is_closed;

    static InfoManager* s_instance;

    /*
     * used for deallocate memory at program completion.
     */
    static StartupShutdownManager::Handler s_shutdown_handler;

private:

    DISALLOW_COPY_AND_ASSIGN (InfoManager);

};

} //namespace FreeMAPs

#include "COMMON/info/InfoManager.inl"

#endif
